/* ------------------------------------------------------------ */
/*                       file information                       */
/* ------------------------------------------------------------ */

// Filename:  eprintf.c
// Purpose:   TTY and error-message routines
// License:   MIT/X. (c) OldCoder (Robert Kiraly) 1987-2022.

/* ------------------------------------------------------------ */
/*                         header files                         */
/* ------------------------------------------------------------ */

/* The "EPRINTF_P" definition used below suppresses some of the */
/* prototypes in  "x3file.h" locally.  This allows us to imple- */
/* ment  variable-length argument lists in a non-standard  (but */
/* generally portable) fashion.                                 */

#define EPRINTF_P               /* see explanation above        */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "inc/eprintf.h"

/* ------------------------------------------------------------ */
/*                          functions                           */
/* ------------------------------------------------------------ */

/* Function:    V_FUNC init_tty(NO_PARAM)                       */
/* Summary:     Initializes the UX3 TTY flags.                  */

/* ------------------------------------------------------------ */

/* "init_tty()"  sets three global character variables  as fol- */
/* lows:                                                        */
/*                                                              */
/*      tty_in  -- standard input  stream TTY mode              */
/*      tty_out -- standard output stream TTY mode              */
/*      tty_err -- standard error  stream TTY mode              */

/* TTY modes are  determined by the standard  library  function */
/* "isatty()".                                                  */

/* E.g., "init_tty()" sets these  three flags  true if and only */
/* if the associated streams are console devices.               */

/* The  global   character  variable  "tty_set"  flags the  TTY */
/* initialization  status.  "tty_set" is  true if  "init_tty()" */
/* has been called previously.                                  */

/* ------------------------------------------------------------ */

V_FUNC init_tty (NO_PARAM)
{
    tty_in  = isatty (0);       /* standard-input  TTY flag     */
    tty_out = isatty (1);       /* standard-output TTY flag     */
    tty_err = isatty (2);       /* standard-error  TTY flag     */
    tty_set = TRUE;             /* TTY  initialization flag     */
}

/* ------------------------------------------------------------ */

/* "eprintf(s,...)"  accepts a  "printf()"-style argument list, */
/* writes the specified  message to the  standard error stream, */
/* and flushes the stream.                                      */

/* This function may be system-dependent.                       */

/* ------------------------------------------------------------ */

V_FUNC eprintf (s,a,b,c,d,e,f,g,h,i,j)
char *s;                        /* format string                */
unsigned long a,b,c,d,e,f,g,h,i,j;        /* dummy arguments              */
{
    fflush (stdout);            /* flush standard output stream */

    fprintf (stderr,            /* print  message to  the       */
        s,a,b,c,d,e,f,g,h,i,j); /* standard error stream        */

    fflush (stderr);            /* flush standard error  stream */
}

/* ------------------------------------------------------------ */

/* "eprintf2(s,...)"  accepts a "printf()"-style argument list, */
/* writes the specified  message to the  standard error stream, */
/* and flushes the stream.                                      */

/* If the  standard output  and  standard error  TTY modes  are */
/* different,  "eprintf2()"  will  write  the  message  to  the */
/* standard output stream as well.  TTY modes are determined by */
/* the standard library function "isatty()".                    */

/* This function may be system-dependent.                       */

/* ------------------------------------------------------------ */

V_FUNC eprintf2 (s,a,b,c,d,e,f,g,h,i,j)
char *s;                        /* format string                */
unsigned long a,b,c,d,e,f,g,h,i,j;        /* dummy arguments              */
{
    fflush (stdout);            /* flush standard output stream */

    fprintf (stderr,            /* print  message to  the       */
        s,a,b,c,d,e,f,g,h,i,j); /* standard error stream        */

    fflush (stderr);            /* flush standard error  stream */
    if (!tty_set) init_tty();   /* initialize TTY mode flags    */

    if (tty_out == tty_err)     /* split the error stream?      */
    {                           /* no                           */
        return;                 /* done - exit                  */
    }

    fprintf (stdout,            /* print  message to  the stan- */
        s,a,b,c,d,e,f,g,h,i,j); /* dard output stream           */

    fflush (stdout);            /* flush standard output stream */
}

/* ------------------------------------------------------------ */

/* "z_msg(t_flag,pf,s,...)" accepts the following arguments:    */
/*                                                              */
/*      t_flag  --  terminate-caller flag                       */
/*      pf      --  prefix-string pointer                       */
/*      s, ...  --  "printf()"-style argument list              */

/* "z_msg()" writes the  specified  "printf()"-style message to */
/* the standard error  stream,  appends a newline,  and flushes */
/* the stream.                                                  */

/* If the  standard output  and  standard error  TTY modes  are */
/* different,  "z_msg()" will write the message to the standard */
/* output  stream  as well.  TTY modes are  determined  by  the */
/* standard library function "isatty()".                        */

/* If the  prefix-string pointer  "pf" is not  NULL,  "z_msg()" */
/* prepends the specified string to the message produced.       */

/* If the  terminate-caller  flag  "t_flag" is  true (nonzero), */
/* "z_msg()" terminates the caller upon completion.             */

/* This function may be system-dependent.                       */

/* ------------------------------------------------------------ */

MODPRIV V_FUNC z_msg(t_flag,pf,s,a,b,c,d,e,f,g,h,i,j)
int t_flag;                     /* terminate-caller flag        */
char *pf;                       /* prefix pointer (or NULL)     */
char *s;                        /* format string                */
unsigned long a,b,c,d,e,f,g,h,i,j;        /* dummy arguments              */
{
    if ((pf != NULLCP) && (*pf != CH_EOS)) eprintf2 ("%s",pf);
    eprintf2 (s,a,b,c,d,e,f,g,h,i,j);
    eprintf2 ("\n");            /* append a newline             */
    if (t_flag) exit (ONE);     /* terminate the caller         */
}

/* ------------------------------------------------------------ */

/* "x_warn(s,...)"  accepts  a  "printf()"-style  argument list */
/* and writes an warning message based on  the argument list to */
/* the standard error stream.                                   */

/* If the  standard output  and  standard error  TTY modes  are */
/* different, "x_warn()" will write the message to the standard */
/* output  stream  as well.  TTY modes are  determined  by  the */
/* standard library function "isatty()".                        */

/* This function may be system-dependent.                       */

/* ------------------------------------------------------------ */

V_FUNC x_warn(s,a,b,c,d,e,f,g,h,i,j)
char *s;                        /* format string                */
unsigned long a,b,c,d,e,f,g,h,i,j;        /* dummy arguments              */
{
    z_msg (FALSE, ":", s,a,b,c,d,e,f,g,h,i,j);
}

/* ------------------------------------------------------------ */

/* "x_error(s,...)"  accepts a  "printf()"-style argument list, */
/* writes an  error message  based on  the argument list to the */
/* standard error stream, and terminates the caller.            */

/* If the  standard output  and  standard error  TTY modes  are */
/* different,  "x_error()"  will  write   the  message  to  the */
/* standard output stream as well.  TTY modes are determined by */
/* the standard library function "isatty()".                    */

/* This function may be system-dependent.                       */

/* ------------------------------------------------------------ */

V_FUNC x_error(s,a,b,c,d,e,f,g,h,i,j)
char *s;                        /* format string                */
long a,b,c,d,e,f,g,h,i,j;        /* dummy arguments              */
{
    z_msg (TRUE, ":", s,a,b,c,d,e,f,g,h,i,j);
}

/* ------------------------------------------------------------ */

/* "x_panic(s,...)" accepts a  "printf()"-style  argument list, */
/* writes an  error message  based on  the argument list to the */
/* standard error stream, and terminates the caller.            */

/* If the  standard output  and  standard error  TTY modes  are */
/* different, "x_panic" will write  the message to the standard */
/* output  stream  as well.  TTY modes are  determined  by  the */
/* standard library function "isatty()".                        */

/* "x_panic" is called primarily to handle internal consistency */
/* errors.                                                      */

/* This function may be system-dependent.                       */

/* ------------------------------------------------------------ */

V_FUNC x_panic (s,a,b,c,d,e,f,g,h,i,j)
char *s;                        /* format string                */
unsigned long a,b,c,d,e,f,g,h,i,j;        /* dummy arguments              */
{
    z_msg (TRUE, "INTERNAL ERROR! :",
        s,a,b,c,d,e,f,g,h,i,j);
}

/* ------------------------------------------------------------ */

/* "n_panic(n)"  prints an error message of  the following form */
/* and terminates the caller:                                   */
/*                                                              */
/*      Internal error: #123                                    */

/* The  integer  "n"  is  used for  the  "#..." portion  of the */
/* message.                                                     */

/* "n_panic()" writes the message to the standard error stream. */

/* If the  standard output  and  standard error  TTY modes  are */
/* different,  "n_panic()" will write the message to the  stan- */
/* dard output stream as well.  TTY modes are determined by the */
/* standard library function "isatty()".                        */

/* "n_panic()"  is called  primarily to  handle  internal  con- */
/* sistency errors.                                             */

/* This function may be system-dependent.                       */

/* ------------------------------------------------------------ */

V_FUNC n_panic(n)
REG_VAR int n;                  /* "panic" number               */
{
    x_panic ("#%d",n,0,0,0,0,0,0,0,0,0);
}
